package main

import "fmt"

/*
	一个切片的容量可以被看作是透过这个窗口最多可以看到的底层数组中元素的个数。

问题 1：怎样估算切片容量的增长？
	一旦一个切片无法容纳更多的元素，Go语言就会想办法扩容。
	但它并不会改变原来的切片，而是会生成一个容量更大的切片，然后将把原有的元素和新元素一并拷贝到新切片中。
	在一般的情况下，你可以简单地认为新切片的容量（以下简称新容量）将会是原切片容量（以下简称原容量）的2倍。

	但是，当原切片的长度（以下简称原长度）大于或等于1024时，Go语言将会以原容量的1.25倍作为新容量的基准（以下新容量基准）。
	新容量基准会被调整（不断地与1.25相乘），直到结果不小于原长度与要追加的元素数量之和（以下简称新长度）。
	最终，新容量往往会比新长度大一些，当然，相等也是可能的。

	另外，如果一次追加的元素过多，以至于使新长度比原容量的2倍还要大，那么新容量就会以新长度为基准。

问题 2：切片的底层数组什么时候会被替换？
	确切地说，一个切片的底层数组永远不会被替换。为什么？虽然在扩容的时候 Go 语言一定会生成新的底层数组，但是它也同时生成了新的切片。
	它只是把新的切片作为了新底层数组的窗口，而没有对原切片，及其底层数组做任何改动。

	在无需扩容时，append函数返回的是指向原底层数组的新切片，而在需要扩容时，append函数返回的是指向新底层数组的新切片。
	只要新长度不会超过切片的原容量，那么使用append函数对其追加元素的时候就不会引起扩容。
 */
func main() {

	slice01 :=make([]int, 5)
	fmt.Printf("The length of slice01: %d\n", len(slice01))
	fmt.Printf("The capacity of slice01: %d\n", cap(slice01))
	fmt.Printf("The value of slice01: %d\n", slice01)

	slice02 := make([]int, 5, 8)
	fmt.Printf("The length of slice02: %d\n", len(slice02))
	fmt.Printf("The capacity of slice02: %d\n", cap(slice02))
	fmt.Printf("The value of slice02: %d\n", slice02)

	/*
		由于slice04是通过在slice03上施加切片操作得来的，所以slice03的底层数组就是slice04的底层数组。
		又因为，在底层数组不变的情况下，切片代表的窗口可以向右扩展，直至其底层数组的末尾。
		所以，s4的容量就是其底层数组的长度8, 减去上述切片表达式中的那个起始索引3，即5。

		注意，切片代表的窗口是无法向左扩展的。也就是说，我们永远无法透过s4看到s3中最左边的那 3 个元素。
	 */
	slice03 := []int {1, 2, 3, 4, 5, 6, 7, 8}
	slice04 := slice03[3:6]
	fmt.Printf("The length of slice04: %d\n", len(slice04))
	fmt.Printf("The capacity of slice04: %d\n", cap(slice04))
	fmt.Printf("The value of slice04: %d\n", slice04)
}
